
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;

public class Client extends MIDlet implements DiscoveryListener, CommandListener {

    private Form StartServerSearch = null,submitOrder = null;
    private Command ok = null,  back = null,  connect = null,  view = null,  order = null,  remove = null,  sendOrder = null,  add = null,  back2m = null;
    private Display display = null;
    private LocalDevice local = null;
    private DiscoveryAgent agent = null;
    private List DevicesFound = null,  Menu = null,  MenuContents = null,  chosen = null;
    private UUID uuid = new UUID(0X1101);
    private Vector Devices = new Vector();
    private Thread thread = null,  msgthread = null;
    private StreamConnection con = null;
    private DataInputStream in = null;
    private DataOutputStream out = null;
    private TextField clientName;
    private TextField tableName;
    String resp = null,clientName1 = null, tableName1 =null,devname=null;
    String serv = null, menuTitle = "Menu Contents";
    boolean isreading = false;
    int totalPrice = 0, itemPrice = 0;

    public Client() {
        connect = new Command("Connect", Command.OK, 1);
        view = new Command("View", Command.OK, 1);
        remove = new Command("Delete from list", Command.OK, 1);
        back2m = new Command("Back to main menu", Command.OK, 1);
        add = new Command("Add item to list", Command.OK, 1);
        order = new Command("View your list", Command.OK, 1);

        back = new Command("Back", Command.BACK, 1);
        ok = new Command("OK", Command.OK, 1);
        sendOrder = new Command("Submit order", Command.OK, 1);

        //StartServerSearch = new List("Menu Client started", List.IMPLICIT);
        StartServerSearch = new Form("Menu-client");
        try {
            ImageItem logo = new ImageItem("Search for server", Image.createImage("/server1.png"), ImageItem.LAYOUT_CENTER | ImageItem.LAYOUT_NEWLINE_BEFORE | ImageItem.LAYOUT_NEWLINE_AFTER, "server search");
            StartServerSearch.append(logo);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        StartServerSearch.addCommand(ok);
        StartServerSearch.setCommandListener(this);


        
        tableName = new TextField("Table number:","", 2, TextField.NUMERIC);
        submitOrder = new Form("Submiting an order ");
        submitOrder.append(tableName);
        submitOrder.addCommand(sendOrder);
        submitOrder.setCommandListener(this);
        submitOrder.addCommand(back);
        submitOrder.setCommandListener(this);

        Menu = new List("Restaurant Menu", List.IMPLICIT);
        try {
            Menu.append("Food", Image.createImage("/food-icon.png"));
            Menu.append("Drinks", Image.createImage("/drinks.png"));
            Menu.append("Snacks", Image.createImage("/snacks.png"));
            Menu.append("Services", Image.createImage("/services.png"));
            //Menu.append("Request for a waiter", Image.createImage("/waiter.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        Menu.addCommand(view);
        Menu.setCommandListener(this);
        Menu.addCommand(order);
        Menu.setCommandListener(this);

        MenuContents = new List(menuTitle, List.IMPLICIT);

        MenuContents.addCommand(add);
        MenuContents.addCommand(order);
        MenuContents.addCommand(back2m);
        MenuContents.setCommandListener(this);

        chosen = new List("You ordered list contains:", List.IMPLICIT);
        chosen.addCommand(sendOrder);
        chosen.addCommand(remove);
        chosen.addCommand(back2m);
        chosen.setCommandListener(this);

    }

    public void startApp() {
        this.display = Display.getDisplay(this);
        this.display.setCurrent(this.StartServerSearch);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        sendOut("exit", null);
        StartServerSearch = null;
        ok = null;  back = null;  connect = null;  view = null;
        order = null;  remove = null;  sendOrder = null;  add = null;  back2m = null;
        display = null;
        local = null; agent = null;
        DevicesFound = null;  Menu = null;  MenuContents = null;  chosen = null;
        thread = null;  msgthread = null;
        resp = null;
        serv = null;
        in = null;
        out = null;
        con= null;
    }

    public void deviceDiscovered(RemoteDevice remote, DeviceClass arg1) {
        if (!Devices.contains(remote)) {
            Devices.addElement(remote);
        }
    }

    public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {

        for (int i = 0; i < arg1.length; i++) {
            ServiceRecord rec = arg1[i];
            String url = rec.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
            handleConnection(url);

        }
    }

    public void serviceSearchCompleted(int arg0, int arg1) {
        String msg = null;
        switch (arg1) {
            case SERVICE_SEARCH_COMPLETED:
                msg = "the service search completed normally";
                break;
            case SERVICE_SEARCH_TERMINATED:
                msg = "the service search request was cancelled by a call to DiscoveryAgent.cancelServiceSearch()";
                break;
            case SERVICE_SEARCH_ERROR:
                msg = "an error occurred while processing the request";
                break;
            case SERVICE_SEARCH_NO_RECORDS:
                msg = "no records were found during the service search";
                break;
            case SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
                msg = "the device specified in the search request could not be reached or the local device could not establish a connection to the remote device";
                break;
        }
    

    }

    public void inquiryCompleted(int arg0) {

        if (Devices.size() > 0) {
            DevicesFound = new List("Available connections found", List.IMPLICIT);
            DevicesFound.addCommand(back);
            DevicesFound.setCommandListener(this);
            DevicesFound.addCommand(connect);
            DevicesFound.setCommandListener(this);
            for (int i = 0; i < Devices.size(); i++) {
                try {
                    RemoteDevice rd = (RemoteDevice) Devices.elementAt(i);
                    devname=rd.getFriendlyName(true);
                    //append only the device with the server name
                    /*if(devname.equals("MICHAEL-PC")){
                         DevicesFound.append(devname + "(" + rd.getBluetoothAddress() + ")", null);
                    }*/
                    
                    DevicesFound.append(rd.getFriendlyName(true) + "(" + rd.getBluetoothAddress() + ")", null);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
            display.setCurrent(DevicesFound);
        } else {
            AlertsForForms("Server was not found..please search again", 3000, StartServerSearch);
           // display.setCurrent();
        }
    }
 public void AlertsForForms(String str, int timeOut, Form form) {
        Alert alert = new Alert("Notification", str, null, AlertType.INFO);
        alert.setTimeout(timeOut);
        display.setCurrent(alert, form);
    }
    public void Alerts(String str, int timeOut, List ba) {
        Alert a = new Alert("Notification", str, null, AlertType.INFO);
        a.setTimeout(timeOut);
        display.setCurrent(a, ba);
    }

    public void commandAction(Command c, Displayable d) {
        if (d == this.StartServerSearch) {
            if (c == ok) {

                try {
                    local = LocalDevice.getLocalDevice();
                    agent = local.getDiscoveryAgent();
                    local.setDiscoverable(DiscoveryAgent.GIAC);
                    Alert a;

                    a = new Alert("Searching for server", "This may take a while Please Wait...", null, AlertType.INFO);
                    a.setTimeout(Alert.FOREVER);
                    display.setCurrent(a);
                    agent.startInquiry(DiscoveryAgent.GIAC, this);

                } catch (BluetoothStateException ex) {
                    ex.printStackTrace();
                }
            }
        }

        if (d == this.DevicesFound) {
            if (c == connect) {
                String getremoteaddr = (String) DevicesFound.getString(DevicesFound.getSelectedIndex()), remoteadd = null;
                int t = getremoteaddr.indexOf("(", 0);
                remoteadd = getremoteaddr.substring(t + 1, getremoteaddr.length() - 1);

                startservicesearch(new RemoteDevice(remoteadd) {
                });

            } else if (c == back) {
                display.setCurrent(StartServerSearch);
            }

        }
        if (d == this.Menu) {

            if (c == view) {
                if ((Menu.getString(Menu.getSelectedIndex())).equals("Food")) {
                    sendOut("food", "Food Menu");

                } else if ((Menu.getString(Menu.getSelectedIndex())).equals("Drinks")) {
                    sendOut("drinks", "Drinks Menu");

                } else if ((Menu.getString(Menu.getSelectedIndex())).equals("Snacks")) {
                    sendOut("snacks", "Snacks Menu");


                } else if ((Menu.getString(Menu.getSelectedIndex())).equals("Services")) {
                    sendOut("services", "Services Menu");


                }
                /*else if ((Menu.getString(Menu.getSelectedIndex())).equals("Request for a waiter")) {
                    sendOut("Request for a waiter", null);
                    Alerts("Your request was made please wait...", 4000, Menu);

                }*/
            }else if(c == order){
                if (chosen.size() == 0) {
                    Alerts("Currently your list has no items", 3000, MenuContents);
                } else {
                    display.setCurrent(chosen);
                    chosen.append("TOTAL PRICE: " + totalPrice, null);
                }
            }
        }
        if (d == MenuContents) {
            if (MenuContents.size() > 1) {
            } else {
                display.setCurrent(Menu);
            }
            /*if (isreading) {
            msgthread.interrupt();
            isreading = false;
            }*/

            if (c == back2m) {
                display.setCurrent(Menu);
            } else if (c == order) {

                if (chosen.size() == 0) {
                    Alerts("Currently your list has no items", 3000, MenuContents);
                } else {
                    display.setCurrent(chosen);
                    chosen.append("TOTAL PRICE: " + totalPrice, null);
                }

            } else if (c == add && MenuContents.getSelectedIndex() >= 1) {
                String item = MenuContents.getString(MenuContents.getSelectedIndex());
                String sub = item.substring(item.indexOf(":") + 1, item.length());
                itemPrice = Integer.parseInt(sub);
                totalPrice += itemPrice;
                itemPrice = 0;
                Alerts(item + " added to your list" + "\n" + "TOTAL PRICE: " + totalPrice, 4000, MenuContents);
                chosen.append(MenuContents.getString(MenuContents.getSelectedIndex()), null);

            } else if (c == add && MenuContents.getSelectedIndex() == 0) {

                Alerts("Please select an item to add to list", 3000, MenuContents);
            }

        }
        if (d == chosen) {

            if (c == back2m) {
                display.setCurrent(Menu);
                chosen.delete(chosen.size() - 1);
            } else if (c == sendOrder) {
               display.setCurrent(submitOrder);

            } else if (c == remove) {

                if (chosen.size() == 2 && chosen.getSelectedIndex() < (chosen.size() - 1)) {
                    chosen.deleteAll();
                    totalPrice = 0;
                    display.setCurrent(Menu);
                } else if (chosen.size() > 2 && chosen.getSelectedIndex() < (chosen.size() - 1)) {
                    String item = chosen.getString(chosen.getSelectedIndex());
                    String sub = item.substring(item.indexOf(":") + 1, item.length());
                    itemPrice = Integer.parseInt(sub);
                    totalPrice -= itemPrice;
                    itemPrice = 0;
                    chosen.delete(chosen.getSelectedIndex());
                    chosen.delete(chosen.size() - 1);
                    chosen.append("TOTAL PRICE: " + totalPrice, null);
                } else if (chosen.getSelectedIndex() < (chosen.size() - 1)) {
                    Alerts("Please select an Item to remove", 3000, chosen);

                }
            }


        }
        if(d==submitOrder){
            if(c== sendOrder){
                //clientName1 = clientName.getString().trim();
                tableName1 = tableName.getString().trim();
                if(tableName1.equals("")){
                    Alerts("Please enter the table where you will be seated",3000, chosen);
                }else{
                 try {
                     out.writeUTF("% " +tableName1);
                     out.flush();
                     
                    for (int i = 0; i < (chosen.size()); i++) {
                        out.writeUTF(chosen.getString(i));
                        out.flush();

                    }
                    Alerts("You order was submited successfully..please wait", 3000, Menu);
                    chosen.deleteAll();
                    tableName.setString("");
                    MenuContents.deleteAll();
                    totalPrice = 0;
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                }
            }
            else if(c==back){
                display.setCurrent(chosen);
            }
        }
    }



    private void startservicesearch(RemoteDevice remoteDevice) {

        Alert a = new Alert("Connecting to the server address: " + remoteDevice.getBluetoothAddress(), "Please Wait", null, AlertType.INFO);
        a.setTimeout(Alert.FOREVER);
        display.setCurrent(a);
        UUID uuids[] = new UUID[]{uuid};
        try {
            agent.searchServices(null, uuids, remoteDevice, this);
        } catch (BluetoothStateException ex) {
        }

    }

    private void sendOut(String st, String Title) {
        try {
            out.writeUTF(st);
            out.flush();
            if ((st.equals("Request for a waiter") || st.equals("exit"))) {
            } else {
                MenuContents.deleteAll();
                display.setCurrent(MenuContents);
                MenuContents.append(Title + "   ||  Price", null);
                MenuContents.setSelectedIndex(0, false);
                try {
                    out.flush();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }//start the reply thread

        } catch (IOException ex) {
            Alerts("Server Currently OFF.", 3000, Menu);
        }
    }

    private void handleConnection(final String url) {

        display.setCurrent(Menu);
        thread = new Thread() {

            public void run() {
                try {
                    con = (StreamConnection) Connector.open(url);
                    out = con.openDataOutputStream();
                    in = new DataInputStream(con.openInputStream());
                    replymsg(isreading);

                } catch (IOException ex) {
                }



            }
        };
        thread.start();

    }

    private void replymsg(boolean isR) {
        this.isreading = isR;
        msgthread = new Thread() {

            public void run() {
                try {
                    isreading = true;

                    for (;;) {
                        serv = in.readUTF();
                        MenuContents.append("- " + serv, null);

                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        };
        msgthread.start();

    }
}
